/**
 * Interface for a Data Link Layer.
 *
 * @author Timothy Flynn (trflynn@wpi.edu)
 * @version April 10, 2012
 */
#ifndef _DATA_LINK_LAYER_H_
#define _DATA_LINK_LAYER_H_

#include <queue>
#include <pthread.h>
using std::queue;

#include "common.h"
#include "Frame.h"
#include "Packet.h"

extern queue<Packet *> sendPktQ, recvPktQ;
extern queue<Frame *> sendFrameQ, recvFrameQ;
extern pthread_mutex_t sendPktM, recvPktM;
extern pthread_mutex_t sendFrameM, recvFrameM;

// Macro to increment the sequence counter
#define INC(n) ((n) < MAX_SEQ_NUM ? (n)++ : (n) = 0)

// Event enumeration
enum Event { None, FrameArrival, CheckSumError, Timeout, NetworkLayerReady };

// Max window size
#define MAX_SEQ 7

class DataLinkLayer {
public:
	DataLinkLayer();
	virtual ~DataLinkLayer();
	void run();
	void goBackN();

private:
	// A packet may not fit in a frame. Need to store all frames if so.
	queue<Frame *> toSend;

	// Sequence numbers
	short nextToSend, frameExpected, ackExpected;

	// Frame/packet creation
	void createFrames(Packet *);
	Packet *createPacket(Frame *);

	// Inter-layer comm
	Packet *fromNetworkLayer();
	void toNetworkLayer(Packet *);
	Frame *fromPhysicalLayer();
	void toPhysicalLayer();

	// Event handling
	void waitForEvent(Event *);

	// Timers
	void startTimer(int);
	void stopTimer(int);

	// NL enablers
	bool NLEnabled;
	void enableNetworkLayer(bool);
};

#endif
